import cv2
import numpy as np
import matplotlib.pyplot as plt
from skimage import util
import random
# 读取原始图像
img = cv2.imread("cvtest2.jpg")

# 将BGR色彩空间转换为RGB，用于matplotlib显示
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 转换为灰度图像，便于后续处理
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 显示原始图像和灰度图像
#plt.figure(figsize=(10, 5))
#plt.subplot(121), plt.imshow(img_rgb), plt.title('Original RGB Image')
#plt.subplot(122), plt.imshow(img_gray, cmap='gray'), plt.title('Grayscale Image')
#plt.show()

# 添加高斯噪声
def add_gaussian_noise(image, mean=0, sigma=25):
    row, col = image.shape
    gaussian = np.random.normal(mean, sigma, (row, col))
    noisy_image = image + gaussian
    noisy_image = np.clip(noisy_image, 0, 255)  # 确保像素值在0-255范围内
    return noisy_image.astype(np.uint8)

# 添加椒盐噪声
def add_salt_pepper_noise(image, salt_prob=0.01, pepper_prob=0.01):
    noisy_image = np.copy(image)
    # 添加盐噪声（白点）
    salt_mask = np.random.random(image.shape) < salt_prob
    noisy_image[salt_mask] = 255
    # 添加椒噪声（黑点）
    pepper_mask = np.random.random(image.shape) < pepper_prob
    noisy_image[pepper_mask] = 0
    return noisy_image

# 对灰度图像添加噪声
gaussian_noisy = add_gaussian_noise(img_gray)
salt_pepper_noisy = add_salt_pepper_noise(img_gray)

# 显示带噪声的图像
#plt.figure(figsize=(15, 5))
#plt.subplot(131), plt.imshow(img_gray, cmap='gray'), plt.title('Original Grayscale')
#plt.subplot(132), plt.imshow(gaussian_noisy, cmap='gray'), plt.title('Gaussian Noise')
#plt.subplot(133), plt.imshow(salt_pepper_noisy, cmap='gray'), plt.title('Salt & Pepper Noise')
#plt.show()

# 手动实现均值滤波
def manual_mean_filter(image, kernel_size=3):
    # 创建输出图像
    filtered_image = np.zeros_like(image)

    # 计算填充大小
    pad = kernel_size // 2

    # 给图像添加边界填充
    padded_image = cv2.copyMakeBorder(image, pad, pad, pad, pad, cv2.BORDER_REFLECT)

    # 遍历图像中的每个像素
    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            # 提取当前核区域
            region = padded_image[i:i + kernel_size, j:j + kernel_size]
            # 计算区域均值并赋值给输出图像
            filtered_image[i, j] = np.mean(region)

    return filtered_image

# 使用OpenCV的高斯滤波
def opencv_gaussian_filter(image, kernel_size=3):
    return cv2.GaussianBlur(image, (kernel_size, kernel_size), 0)

# 使用OpenCV的中值滤波
def opencv_median_filter(image, kernel_size=3):
    return cv2.medianBlur(image, kernel_size)

# 对高斯噪声图像应用各种滤波
manual_mean_gaussian = manual_mean_filter(gaussian_noisy, 5)
opencv_gaussian_gaussian = opencv_gaussian_filter(gaussian_noisy, 5)
opencv_median_gaussian = opencv_median_filter(gaussian_noisy, 5)

# 对椒盐噪声图像应用各种滤波
manual_mean_sp = manual_mean_filter(salt_pepper_noisy, 5)
opencv_gaussian_sp = opencv_gaussian_filter(salt_pepper_noisy, 5)
opencv_median_sp = opencv_median_filter(salt_pepper_noisy, 5)

# 显示高斯噪声图像的滤波结果
plt.figure(figsize=(10, 10))
plt.subplot(231), plt.imshow(gaussian_noisy, cmap='gray'), plt.title('Gaussian Noisy Image')
plt.subplot(232), plt.imshow(manual_mean_gaussian, cmap='gray'), plt.title('Manual Mean Filter')
plt.subplot(234), plt.imshow(opencv_gaussian_gaussian, cmap='gray'), plt.title('OpenCV Gaussian Filter')
plt.subplot(235), plt.imshow(opencv_median_gaussian, cmap='gray'), plt.title('OpenCV Median Filter')
plt.tight_layout()
plt.show()

# 显示椒盐噪声图像的滤波结果
plt.figure(figsize=(10, 10))
plt.subplot(231), plt.imshow(salt_pepper_noisy, cmap='gray'), plt.title('Salt & Pepper Noisy Image')
plt.subplot(232), plt.imshow(manual_mean_sp, cmap='gray'), plt.title('Manual Mean Filter')
plt.subplot(234), plt.imshow(opencv_gaussian_sp, cmap='gray'), plt.title('OpenCV Gaussian Filter')
plt.subplot(235), plt.imshow(opencv_median_sp, cmap='gray'), plt.title('OpenCV Median Filter')
plt.tight_layout()
plt.show()